home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / tde40.zip / diff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  24.0 KB  |  757 lines

  1. /*
  2.  * Being that the windows in TDE are numbered and lettered, we can easily
  3.  * prompt for windows to diff.  Might as well do a few standard diff
  4.  * options:  ignore leading space, ignore all space, ignore blank lines,
  5.  * ignore end-of-line, and Ignore/Match case.  Once the diff is defined,
  6.  * just press one key to find the next diff.  Any two visible windows may
  7.  * be diffed, which is really nice for comparing similar functions or
  8.  * data in seperate areas of a file.
  9.  *
  10.  *
  11.  * New editor name:  TDE, the Thomson-Davis Editor.
  12.  * Author:           Frank Davis
  13.  * Date:             June 5, 1991, version 1.0
  14.  * Date:             July 29, 1991, version 1.1
  15.  * Date:             October 5, 1991, version 1.2
  16.  * Date:             January 20, 1992, version 1.3
  17.  * Date:             February 17, 1992, version 1.4
  18.  * Date:             April 1, 1992, version 1.5
  19.  * Date:             June 5, 1992, version 2.0
  20.  * Date:             October 31, 1992, version 2.1
  21.  * Date:             April 1, 1993, version 2.2
  22.  * Date:             June 5, 1993, version 3.0
  23.  * Date:             August 29, 1993, version 3.1
  24.  * Date:             November 13, 1993, version 3.2
  25.  * Date:             June 5, 1994, version 4.0
  26.  *
  27.  * This code is released into the public domain, Frank Davis.
  28.  * You may distribute it freely.
  29.  */
  30.  
  31. #include "tdestr.h"
  32. #include "common.h"
  33. #include "define.h"
  34. #include "tdefunc.h"
  35.  
  36.  
  37. /*
  38.  * Name:    define_diff
  39.  * Purpose: get info needed to initialize diff
  40.  * Date:    October 31, 1992
  41.  * Passed:  window:  pointer to current window
  42.  * Notes:   allow the user to start the diff at the beginning of the
  43.  *            file or at the current cursor location.  once the diff
  44.  *            has been defined, the user may press one key to diff again.
  45.  *          user may diff any two visible windows on the screen.
  46.  */
  47. int  define_diff( TDE_WIN *window )
  48. {
  49. int  rc;
  50. int  num1;
  51. int  let1;
  52. int  num2;
  53. int  let2;
  54. int  start;
  55. char temp[MAX_COLS+2];
  56. char answer[MAX_COLS+2];
  57. #if defined( __UNIX__ )
  58.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  59. #else
  60.  char display_buff[(MAX_COLS+2)*2];
  61. #endif
  62.  
  63.    rc = OK;
  64.  
  65.    /*
  66.     * get window number and letter of the first diff window.  then,
  67.     *   verify that window - does it exit? is it visible?
  68.     */
  69.    if (rc == OK) {
  70.       *temp = '\0';
  71.       rc = get_name( diff_prompt1, window->bottom_line, temp,
  72.                      g_display.message_color );
  73.    }
  74.  
  75.    if (rc == OK) {
  76.       rc = verify_number( temp, &num1 );
  77.       if (rc == OK)
  78.          rc = verify_letter( temp, &let1, &diff.w1 );
  79.    }
  80.  
  81.    if (rc == ERROR) {
  82.       combine_strings( answer, diff_prompt6a, temp, diff_prompt6b );
  83.       error( WARNING, window->bottom_line, answer );
  84.       return( ERROR );
  85.    }
  86.  
  87.    /*
  88.     * get and verify the next window number and letter to diff.
  89.     */
  90.    *temp = '\0';
  91.    rc = get_name( diff_prompt2, window->bottom_line, temp,
  92.                   g_display.message_color );
  93.    if (rc == OK) {
  94.       rc = verify_number( temp, &num2 );
  95.       if (rc == OK)
  96.          rc = verify_letter( temp, &let2, &diff.w2 );
  97.    }
  98.    if (rc == ERROR) {
  99.       combine_strings( answer, diff_prompt6a, temp, diff_prompt6b );
  100.       error( WARNING, window->bottom_line, answer );
  101.       return( ERROR );
  102.    }
  103.  
  104.    /*
  105.     * are leading spaces significant?
  106.     */
  107.    save_screen_line( 0, window->bottom_line, display_buff );
  108.    set_prompt( diff_prompt7a, window->bottom_line );
  109.    start = get_yn( );
  110.    restore_screen_line( 0, window->bottom_line, display_buff );
  111.    if (start != ERROR)
  112.       diff.leading =  start == A_YES ?  TRUE  :  FALSE;
  113.    else
  114.       return( ERROR );
  115.  
  116.    /*
  117.     * are all spaces significant?
  118.     */
  119.    save_screen_line( 0, window->bottom_line, display_buff );
  120.    set_prompt( diff_prompt7b, window->bottom_line );
  121.    start = get_yn( );
  122.    restore_screen_line( 0, window->bottom_line, display_buff );
  123.    if (start != ERROR) {
  124.       if (start == A_YES)
  125.          diff.leading = diff.all_space = TRUE;
  126.       else
  127.          diff.all_space = FALSE;
  128.    } else
  129.       return( ERROR );
  130.  
  131.    /*
  132.     * are blank lines significant?
  133.     */
  134.    save_screen_line( 0, window->bottom_line, display_buff );
  135.    set_prompt( diff_prompt7c, window->bottom_line );
  136.    start = get_yn( );
  137.    restore_screen_line( 0, window->bottom_line, display_buff );
  138.    if (start != ERROR)
  139.       diff.blank_lines =  start == A_YES  ?  TRUE : FALSE;
  140.    else
  141.       return( ERROR );
  142.  
  143.    /*
  144.     * is end of line significant?
  145.     */
  146.    save_screen_line( 0, window->bottom_line, display_buff );
  147.    set_prompt( diff_prompt7d, window->bottom_line );
  148.    start = get_yn( );
  149.    restore_screen_line( 0, window->bottom_line, display_buff );
  150.    if (start != ERROR)
  151.       diff.ignore_eol =  start == A_YES  ?  TRUE : FALSE;
  152.    else
  153.       return( ERROR );
  154.  
  155.    /*
  156.     * now, find out were to start the diff -- beginning of file or
  157.     *   current cursor location.
  158.     */
  159.    save_screen_line( 0, window->bottom_line, display_buff );
  160.    set_prompt( diff_prompt3, window->bottom_line );
  161.    start = get_bc( );
  162.    restore_screen_line( 0, window->bottom_line, display_buff );
  163.  
  164.    if (start != ERROR) {
  165.       entab_linebuff( );
  166.       if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  167.          return( ERROR );
  168.  
  169.       /*
  170.        * if everything is everything, initialize the diff pointers.
  171.        */
  172.       diff.defined = TRUE;
  173.       if (start == BEGINNING) {
  174.          diff.d1 = diff.w1->file_info->line_list;
  175.          diff.d2 = diff.w2->file_info->line_list;
  176.          diff.rline1 = 1L;
  177.          diff.rline2 = 1L;
  178.          diff.bin_offset1 = 0;
  179.          diff.bin_offset2 = 0;
  180.          rc = differ( 0, 0, window->bottom_line );
  181.       } else {
  182.          diff.d1 = diff.w1->ll;
  183.          diff.d2 = diff.w2->ll;
  184.          diff.rline1 = diff.w1->rline;
  185.          diff.rline2 = diff.w2->rline;
  186.          diff.bin_offset1 = diff.w1->bin_offset;
  187.          diff.bin_offset2 = diff.w2->bin_offset;
  188.          rc = differ( diff.w1->rcol, diff.w2->rcol, window->bottom_line );
  189.       }
  190.    }
  191.    return( rc );
  192. }
  193.  
  194.  
  195. /*
  196.  * Name:    repeat_diff
  197.  * Purpose: compare two cursor positions
  198.  * Date:    October 31, 1992
  199.  * Passed:  window:  pointer to current window
  200.  * Notes:   user may press this key at any time once the diff has been
  201.  *            defined.
  202.  */
  203. int  repeat_diff( TDE_WIN *window )
  204. {
  205. register int rc = ERROR;
  206.  
  207.    if (diff.defined) {
  208.       entab_linebuff( );
  209.       if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  210.          return( ERROR );
  211.  
  212.       /*
  213.        * initialize the diff pointers.
  214.        */
  215.       diff.d1 = diff.w1->ll;
  216.       diff.d2 = diff.w2->ll;
  217.       diff.rline1 = diff.w1->rline;
  218.       diff.rline2 = diff.w2->rline;
  219.       diff.bin_offset1 = diff.w1->bin_offset;
  220.       diff.bin_offset2 = diff.w2->bin_offset;
  221.       rc = differ( diff.w1->rcol, diff.w2->rcol, window->bottom_line );
  222.    } else
  223.       error( WARNING, window->bottom_line, diff_prompt5 );
  224.    return( rc );
  225. }
  226.  
  227.  
  228. /*
  229.  * Name:    differ
  230.  * Purpose: diff text pointers
  231.  * Date:    October 31, 1992
  232.  * Passed:  initial_rcol1:  beginning column to begin diff in window1
  233.  *          initial_rcol2:  beginning column to begin diff in window2
  234.  *          bottom:         line to display diagnostics
  235.  * Notes:   a straight diff on text pointers is simple; however, diffing
  236.  *            with leading spaces and tabs is kinda messy.  let's do the
  237.  *            messy diff.
  238.  */
  239. int  differ( int initial_rcol1, int initial_rcol2, int bottom )
  240. {
  241. int  rcol1;             /* virtual real column on diff window 1 */
  242. int  rcol2;             /* virtual real column on diff window 2 */
  243. int  r1;                /* real real column rcol1 - needed for tabs */
  244. int  r2;                /* real real column rcol2 - needed for tabs */
  245. char c1;                /* character under r1 */
  246. char c2;                /* character under r2 */
  247. int  leading1;          /* adjustment for leading space in window 1 */
  248. int  leading2;          /* adjustment for leading space in window 2 */
  249. int  len1;              /* length of diff1 line */
  250. int  len2;              /* length of diff2 line */
  251. line_list_ptr node1;    /* scratch node in window 1 */
  252. line_list_ptr node2;    /* scratch node in window 2 */
  253. text_ptr diff1;         /* scratch text ptr in window 1 */
  254. text_ptr diff2;         /* scratch text ptr in window 2 */
  255. long rline1;            /* real line number of diff pointer 1 */
  256. long rline2;            /* real line number of diff pointer 2 */
  257. long bin_offset1;       /* binary offset of diff pointer 1 */
  258. long bin_offset2;       /* binary offset of diff pointer 2 */
  259. int  len;               /* line length variable */
  260. register int tabs;      /* local variable for mode.inflate_tabs, T or F */
  261. #if defined( __UNIX__ )
  262.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  263. #else
  264.  char display_buff[(MAX_COLS+2)*2];
  265. #endif
  266.  
  267.    /*
  268.     * initialize the text pointers and the initial column.  skip any
  269.     *  initial blank lines.
  270.     */
  271.    rline1 = diff.rline1;
  272.    rline2 = diff.rline2;
  273.    node1 = diff.d1;
  274.    node2 = diff.d2;
  275.    bin_offset1 = diff.bin_offset1;
  276.    bin_offset2 = diff.bin_offset2;
  277.    tabs  = mode.inflate_tabs;
  278.    if (diff.blank_lines) {
  279.       while (node1->len != EOF  && is_line_blank( node1->line, node1->len )) {
  280.          bin_offset1 += node1->len;
  281.          node1 = node1->next;
  282.          ++rline1;
  283.          initial_rcol1 = 0;
  284.       }
  285.       while (node2->len != EOF  && is_line_blank( node2->line , node2->len)) {
  286.          bin_offset2 += node2->len;
  287.          node2 = node2->next;
  288.          ++rline2;
  289.          initial_rcol2 = 0;
  290.       }
  291.    }
  292.  
  293.    /*
  294.     * if everything is everything, initialize the diff variables and diff.
  295.     */
  296.    if (node1->len != EOF  &&  node2->len != EOF) {
  297.       diff1 = node1->line;
  298.       diff2 = node2->line;
  299.       rcol1 = initial_rcol1;
  300.       rcol2 = initial_rcol2;
  301.       len1  = node1->len;
  302.       len2  = node2->len;
  303.  
  304.       assert( rcol1 >= 0 );
  305.       assert( rcol1 < MAX_LINE_LENGTH );
  306.       assert( rcol2 >= 0 );
  307.       assert( rcol2 < MAX_LINE_LENGTH );
  308.       assert( len1 >= 0 );
  309.       assert( len1 < MAX_LINE_LENGTH );
  310.       assert( len2 >= 0 );
  311.       assert( len2 < MAX_LINE_LENGTH );
  312.  
  313.       /*
  314.        * if cursors are past EOL, move them back to EOL.
  315.        */
  316.       len = find_end( diff1, len1 );
  317.       if (rcol1 > len)
  318.          rcol1 = len;
  319.       len = find_end( diff2, len2 );
  320.       if (rcol2 > len)
  321.          rcol2 = len;
  322.  
  323.       /*
  324.        * if skip leading space, make sure our cursors start on first non-space.
  325.        */
  326.       if (diff.leading) {
  327.          leading1 = skip_leading_space( diff1, len1 );
  328.          leading2 = skip_leading_space( diff2, len2 );
  329.          if (tabs) {
  330.             leading1 = detab_adjust_rcol( diff1, leading1 );
  331.             leading2 = detab_adjust_rcol( diff2, leading2 );
  332.          }
  333.          if (rcol1 < leading1)
  334.             rcol1 = leading1;
  335.          if (rcol2 < leading2)
  336.             rcol2 = leading2;
  337.       }
  338.  
  339.       /*
  340.        * we now have a valid rcol for the diff start, we may need to adjust
  341.        *   for tabs, though.
  342.        */
  343.       assert( rcol1 >= 0 );
  344.       assert( rcol1 < MAX_LINE_LENGTH );
  345.       assert( rcol2 >= 0 );
  346.       assert( rcol2 < MAX_LINE_LENGTH );
  347.  
  348.       r1 =  tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  349.       r2 =  tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  350.  
  351.       assert( r1 >= 0 );
  352.       assert( r1 <= len1 );
  353.       assert( r2 >= 0 );
  354.       assert( r2 <= len2 );
  355.       assert( r1 <= rcol1 );
  356.       assert( r2 <= rcol2 );
  357.  
  358.       s_output( diff_message, g_display.mode_line, 67, g_display.diag_color );
  359.       while (node1->len != EOF  &&  node2->len != EOF  &&
  360.                          !g_status.control_break) {
  361.  
  362.          /*
  363.           * look at each character in each diff window
  364.           */
  365.          c1 = (char)(r1 < len1 ? *(diff1 + r1)  : 0);
  366.          c2 = (char)(r2 < len2 ? *(diff2 + r2)  : 0);
  367.  
  368.          /*
  369.           *  tabs == space
  370.           */
  371.          if (tabs) {
  372.             if (c1 == '\t')
  373.                c1 = ' ';
  374.             if (c2 == '\t')
  375.                c2 = ' ';
  376.          }
  377.  
  378.          /*
  379.           * skip spaces, if needed
  380.           */
  381.          if (diff.all_space) {
  382.             while (c1 == ' '  &&  r1 < len1) {
  383.                ++rcol1;
  384.                r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  385.                c1 =  (char)(r1 < len1  ?  *(diff1 + r1) :  0);
  386.                if (c1 == '\t'  &&  tabs)
  387.                   c1 = ' ';
  388.             }
  389.             while (c2 == ' '  &&  r2 < len2) {
  390.                ++rcol2;
  391.                r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  392.                c2 =  (char)(r2 < len2  ? *(diff2 + r2) : 0);
  393.                if (c2 == '\t'  &&  tabs)
  394.                   c2 = ' ';
  395.             }
  396.          }
  397.  
  398.          /*
  399.           * if one of the node pointers has come to EOL, move to next
  400.           *   diff line.
  401.           */
  402.          if (diff.ignore_eol) {
  403.             if (r1 >= len1) {
  404.                node1 = skip_eol( node1, &r1, &rcol1, &rline1, &bin_offset1 );
  405.                len1  = node1->len;
  406.                if (len1 != EOF) {
  407.                   diff1 = node1->line;
  408.                   c1 =  (char)(r1 < len1  ?  *(diff1 + r1) : 0);
  409.                   if (c1 == '\t'  &&  tabs)
  410.                      c1 = ' ';
  411.                }
  412.             }
  413.             if (r2 >= len2) {
  414.                node2 = skip_eol( node2, &r2, &rcol2, &rline2, &bin_offset2 );
  415.                len2  = node2->len;
  416.                if (len2 != EOF) {
  417.                   diff2 = node2->line;
  418.                   c2 =  (char)(r2 < len2  ? *(diff2 + r2)  :  0);
  419.                   if (c2 == '\t'  &&  tabs)
  420.                      c2 = ' ';
  421.                }
  422.             }
  423.          }
  424.  
  425.          /*
  426.           * convert the characters to lower case, if needed.
  427.           */
  428.          if (mode.search_case == IGNORE) {
  429.             c1 = (char)tolower( c1 );
  430.             c2 = (char)tolower( c2 );
  431.          }
  432.  
  433.          /*
  434.           * diff each character in the diff lines until we reach EOL
  435.           */
  436.          while (r1 < len1  && r2 < len2) {
  437.             if (c1 == c2) {
  438.                if (diff.all_space) {
  439.                   do {
  440.                      ++rcol1;
  441.                      r1 = tabs ? entab_adjust_rcol( diff1,len1,rcol1 ) : rcol1;
  442.                      c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  :  0);
  443.                      if (c1 == '\t'  &&  tabs)
  444.                         c1 = ' ';
  445.                   } while (c1 == ' '  &&  r1 < len1);
  446.                   do {
  447.                      ++rcol2;
  448.                      r2 = tabs ? entab_adjust_rcol( diff2,len2,rcol2 ) : rcol2;
  449.                      c2 =  (char)(r2 < len2  ?  *(diff2 + r2)  :  0);
  450.                      if (c2 == '\t'  &&  tabs)
  451.                         c2 = ' ';
  452.                   } while (c2 == ' '  &&  r2 < len2);
  453.                } else {
  454.                   ++rcol1;
  455.                   ++rcol2;
  456.                   r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  457.                   r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  458.                   c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  :  0);
  459.                   c2 =  (char)(r2 < len2  ?  *(diff2 + r2)  :  0);
  460.                   if (tabs) {
  461.                      if (c1 == '\t')
  462.                         c1 = ' ';
  463.                      if (c2 == '\t')
  464.                         c2 = ' ';
  465.                   }
  466.                }
  467.                if (diff.ignore_eol) {
  468.                   if (r1 >= len1) {
  469.                      node1 = skip_eol(node1, &r1, &rcol1, &rline1,&bin_offset1);
  470.                      len1  = node1->len;
  471.                      if (len1 != EOF) {
  472.                         diff1 = node1->line;
  473.                         c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  : 0);
  474.                         if (c1 == '\t'  &&  tabs)
  475.                            c1 = ' ';
  476.                      }
  477.                   }
  478.                   if (r2 >= len2) {
  479.                      node2 = skip_eol(node2, &r2, &rcol2, &rline2,&bin_offset2);
  480.                      len2  = node2->len;
  481.                      if (len2 != EOF) {
  482.                         diff2 = node2->line;
  483.                         c2 = (char)(r2 < len2  ? *(diff2 + r2)  :  0);
  484.                         if (c2 == '\t'  &&  tabs)
  485.                            c2 = ' ';
  486.                      }
  487.                   }
  488.                }
  489.                if (mode.search_case == IGNORE) {
  490.                   c1 = (char)tolower( c1 );
  491.                   c2 = (char)tolower( c2 );
  492.                }
  493.             } else {
  494.  
  495.                /*
  496.                 * when we show the diff, use rcol1 and rcol2, as
  497.                 *   find_adjust does not adjust rcol for tabs.
  498.                 */
  499.                update_line( diff.w1 );
  500.                diff.w1->bin_offset = bin_offset1;
  501.                find_adjust( diff.w1, node1, rline1, rcol1 );
  502.                check_virtual_col( diff.w1, rcol1, rcol1 );
  503.                show_diff_window( diff.w1 );
  504.                update_line( diff.w2 );
  505.                diff.w2->bin_offset = bin_offset2;
  506.                bin_offset_adjust( diff.w2, rline2 );
  507.                find_adjust( diff.w2, node2, rline2, rcol2 );
  508.                check_virtual_col( diff.w2, rcol2, rcol2 );
  509.                show_diff_window( diff.w2 );
  510.                s_output( diff_blank, g_display.mode_line, 67,
  511.                          g_display.mode_color );
  512.                return( OK );
  513.             }
  514.          }
  515.  
  516.          /*
  517.           * if we haven't come to the end of a file buffer, check the last
  518.           *   characters.  see if pointers are at EOL.
  519.           */
  520.          if (node1->len != EOF && node2->len != EOF) {
  521.             if (r1 != len1  &&  r2 != len2) {
  522.                update_line( diff.w1 );
  523.                diff.w1->bin_offset = bin_offset1;
  524.                find_adjust( diff.w1, node1, rline1, rcol1 );
  525.                show_diff_window( diff.w1 );
  526.                update_line( diff.w2 );
  527.                diff.w2->bin_offset = bin_offset2;
  528.                find_adjust( diff.w2, node2, rline2, rcol2 );
  529.                show_diff_window( diff.w2 );
  530.                s_output( diff_blank, g_display.mode_line, 67,
  531.                          g_display.mode_color );
  532.                return( OK );
  533.             } else {
  534.                if (r1 == len1) {
  535.                   node1 = skip_eol( node1, &r1, &rcol1, &rline1, &bin_offset1 );
  536.                   len1  = node1->len;
  537.                   diff1 = node1->line;
  538.                }
  539.                if (r2 == len2) {
  540.                   node2 = skip_eol( node2, &r2, &rcol2, &rline2, &bin_offset2 );
  541.                   len2  = node2->len;
  542.                   diff2 = node2->line;
  543.                }
  544.             }
  545.          }
  546.  
  547.          assert( rcol1 >= 0 );
  548.          assert( rcol1 < MAX_LINE_LENGTH );
  549.          assert( rcol2 >= 0 );
  550.          assert( rcol2 < MAX_LINE_LENGTH );
  551.          assert( r1 >= 0 );
  552.          assert( r1 < MAX_LINE_LENGTH );
  553.          assert( r2 >= 0 );
  554.          assert( r2 < MAX_LINE_LENGTH );
  555.          assert( r1 <= rcol1 );
  556.          assert( r2 <= rcol2 );
  557.          if (node1->len == EOF)
  558.             assert( len1 == EOF );
  559.          else {
  560.             assert( len1 >= 0 );
  561.             assert( len1 < MAX_LINE_LENGTH );
  562.          }
  563.          if (node2->len == EOF)
  564.             assert( len2 == EOF );
  565.          else {
  566.             assert( len2 >= 0 );
  567.             assert( len2 < MAX_LINE_LENGTH );
  568.          }
  569.       }
  570.       save_screen_line( 0, bottom, display_buff );
  571.       set_prompt( diff_prompt4, bottom );
  572.       getkey( );
  573.       restore_screen_line( 0, bottom, display_buff );
  574.       s_output( diff_blank, g_display.mode_line, 67, g_display.mode_color );
  575.    }
  576.    return( ERROR );
  577. }
  578.  
  579.  
  580. /*
  581.  * Name:    skip_leading_space
  582.  * Purpose: put the diff on the first non-blank character
  583.  * Date:    October 31, 1992
  584.  * Passed:  s:  the string to search
  585.  *          len: length of string
  586.  * Returns: the first non-blank column
  587.  */
  588. int  skip_leading_space( text_ptr s, int len )
  589. {
  590. register int count = 0;
  591.  
  592.    assert( len >= 0 );
  593.    assert( len < MAX_LINE_LENGTH );
  594.  
  595.    if (s != NULL) {
  596.       if (mode.inflate_tabs) {
  597.          while (len > 0  &&  (*s == ' ' || *s == '\t')) {
  598.             ++count;
  599.             ++s;
  600.             --len;
  601.          }
  602.       } else {
  603.          while (len > 0  &&  *s == ' ') {
  604.            ++count;
  605.            ++s;
  606.            --len;
  607.          }
  608.       }
  609.    }
  610.    if (len == 0)
  611.       count = 0;
  612.  
  613.    return( count );
  614. }
  615.  
  616.  
  617. /*
  618.  * Name:    skip_eol
  619.  * Purpose: move the diff to the next line
  620.  * Date:    October 31, 1992
  621.  * Passed:  d:           pointer to current node
  622.  *          r:           tab adjusted real col
  623.  *          rcol:        real real col
  624.  *          rline:       current line number
  625.  *          bin_offset:  offset from the beginning of the file
  626.  * Returns: next non-blank node
  627.  */
  628. line_list_ptr skip_eol( line_list_ptr d, int *r, int *rcol, long *rline,
  629.                         long *bin_offset )
  630. {
  631. int  leading;
  632. long rl;
  633. long bo;
  634.  
  635.    *r = *rcol = 0;
  636.    rl = *rline;
  637.    bo = *bin_offset;
  638.    if (d->len != EOF) {
  639.       bo += d->len;
  640.       d = d->next;
  641.       ++rl;
  642.       if (diff.blank_lines) {
  643.          while (d->len != EOF  &&  is_line_blank( d->line, d->len )) {
  644.             bo += d->len;
  645.             d = d->next;
  646.             ++rl;
  647.          }
  648.       }
  649.       if (d->len != EOF) {
  650.          if (diff.leading) {
  651.             leading = skip_leading_space( d->line, d->len );
  652.             if (mode.inflate_tabs)
  653.                leading = detab_adjust_rcol( d->line, leading );
  654.             *rcol = leading;
  655.          } else
  656.             *rcol = 0;
  657.          *r = *rcol;
  658.          if (mode.inflate_tabs)
  659.             *r = entab_adjust_rcol( d->line, d->len, *rcol );
  660.       }
  661.    }
  662.    *rline = rl;
  663.    *bin_offset = bo;
  664.  
  665.    return( d );
  666. }
  667.  
  668.  
  669. /*
  670.  * Name:    show_diff_window
  671.  * Purpose: update the contents of a diff window
  672.  * Date:    October 31, 1992
  673.  * Passed:  win:  pointer to window
  674.  */
  675. void show_diff_window( TDE_WIN *win )
  676. {
  677.    if (win->file_info->dirty == LOCAL)
  678.       display_current_window( win );
  679.    else
  680.       show_curl_line( win );
  681.    show_line_col( win );
  682.    make_ruler( win );
  683.    show_ruler( win );
  684.    show_ruler_pointer( win );
  685.    win->file_info->dirty = FALSE;
  686. }
  687.  
  688.  
  689. /*
  690.  * Name:    verify_number
  691.  * Purpose: given a window number, verify the number
  692.  * Date:    October 31, 1992
  693.  * Passed:  temp:  string that contains number
  694.  *          num:   successfully converted number.
  695.  */
  696. int  verify_number( char *temp, int *num )
  697. {
  698. register file_infos *fp;
  699.  
  700.    /*
  701.     * see if string has a number.  if string does have a number, convert it.
  702.     */
  703.    if (*temp == '\0' || !bj_isdigit( *temp ))
  704.       return( ERROR );
  705.    *num = 0;
  706.    while (bj_isdigit( *temp ))
  707.       *num = *num * 10 + *temp++ - '0';
  708.  
  709.    /*
  710.     * now that we have a window number, see if any files have that number
  711.     */
  712.    for (fp=g_status.file_list; fp != NULL; fp=fp->next) {
  713.       if (fp->file_no == *num)
  714.          return( OK );
  715.    }
  716.    return( ERROR );
  717. }
  718.  
  719.  
  720.  
  721. /*
  722.  * Name:    verify_letter
  723.  * Purpose: given a window letter, verify the letter
  724.  * Date:    October 31, 1992
  725.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  726.  * Passed:  temp:  string that contains letter
  727.  *          let:   window letter
  728.  *          win:   pointer to window that contains letter and number
  729.  *
  730.  * Change:  Control that the letter is in string windowletters
  731.  */
  732. int  verify_letter( char *temp, int *let, TDE_WIN **win )
  733. {
  734. register file_infos *fp;
  735. register TDE_WIN *wp;
  736. int  num;
  737.  
  738.    if (verify_number( temp, &num ) == OK) {
  739.       while (bj_isdigit( *temp ))
  740.          temp++;
  741.       if (*temp == '\0' || !strchr( windowletters, tolower( *temp )))
  742.          return( ERROR );
  743.       *let = (int)tolower( *temp );
  744.       for (fp=g_status.file_list; fp != NULL; fp=fp->next) {
  745.          if (fp->file_no == num)
  746.             break;
  747.       }
  748.       for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  749.          if (wp->file_info == fp  &&  wp->letter == *let  &&  wp->visible) {
  750.             *win = wp;
  751.             return( OK );
  752.          }
  753.       }
  754.    }
  755.    return( ERROR );
  756. }
  757.